/*
 * @Author: your name
 * @Date: 2021-08-27 20:07:04
 * @LastEditTime: 2022-03-22 20:28:10
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \phone\src\input_item.cpp
 */
#include "input_item.h"
#include "interface.h"
using namespace std::placeholders;
InputItem::InputItem(std::unique_ptr<Widget>& page, std::string& value, Widget* editView, bool commonInputItem, unsigned int editLength)
    : PrimaryContrl(page)
    , InputMethod(page)
    , editValue(value)
    , primaryWidget(page)
    , commonItem(commonInputItem)
    , mEditLength(editLength) // mEditLength默认长度为12，是因为该类是默认为设置界面的通用输入框设计的，后来才拓展到可定制长度。
{
    inputMethodInit = false;
    onlySupport = InputMethodsType::FUNCTION_END;
    InputItem::editView = GuiEngine::GetInstance().NewWidget();
    InputItem::editView->SetWidget(editView);
    SetText(editValue);
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_0)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_1)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_2)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_3)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_4)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_5)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_6)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_7)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_8)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_NUM_9)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_ASTERISK)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_POUND_SIGN)] = { std::bind(&InputItem::Input, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_DIRECTION_LEFT)] = { std::bind(&InputItem::MoveCursor, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_DIRECTION_RIGHT)] = { std::bind(&InputItem::MoveCursor, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_2)] = { std::bind(&InputItem::InputMethodChange, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_3)] = { std::bind(&InputItem::Delete, this, _1) };
    setEvent[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_4)] = { std::bind(&InputItem::SaveData, this, _1) };
    InputInit();
}
InputItem::~InputItem()
{
    /**
     * @brief Construct a new Input Un Init I Q object
     * 在按键事件里面处理控件，不需要使用GuiIdleQueue函数。
     */
    InputUnInitIQ();
    InputMethod::SetInstance(nullptr);
    delete editView;
}
/**
 * @brief
 * 设置项被选中的时候，初始化输入法
 */
void InputItem::InputInit()
{
    inputMethodInit = true;
    InputMethod::SetInstance(this);
    InputInitIQ();
}
void InputItem::InputInitIQ()
{
    if (editView->IsValid()) {
        std::unique_ptr<Widget> view(GuiEngine::GetInstance().NewWidget());
        /**
         * @brief
         * 创建候选字符view
         */
        if (GuiEngine::GetInstance().ViewCreate(InputItem::primaryWidget.get(), 0, 0, 0, 0, view.get())) {
            char params[256] = { 0 };
            GuiEngine::GetInstance().SetName(view.get(), "choose");
            snprintf(params, 256, "default(x=c,y=%d,w=280,h=30)", editView->GetCoordY() > 50 ? editView->GetCoordY() : editView->GetCoordY() + 75);
            // LOG_I("edit view Y = %d, params = %s,\n", editView->GetCoordY(), params);
            GuiEngine::GetInstance().SetSelfLayout(view.get(), params);
            GuiEngine::GetInstance().SetChildrenLayout(view.get(), "default(r=1,c=0,align_h=center,x=0,y=0,s=0)");
        }
        /**
         * @brief
         * 创建输入法切换view
         */
        if (GuiEngine::GetInstance().ViewCreate(InputItem::primaryWidget.get(), 0, 0, 0, 0, view.get())) {
            GuiEngine::GetInstance().SetName(view.get(), "imchoose");
            GuiEngine::GetInstance().SetSelfLayout(view.get(), "default(x=c,y=176,w=80%,h=30)");
            GuiEngine::GetInstance().SetChildrenLayout(view.get(), "default(r=1,c=0,align_h=center,x=0,y=0,s=0)");
        }
        /**
         * @brief
         * 显示和设置删除键
         */
        if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "button3", true, view.get())) {
            // GuiEngine::GetInstance().SetVisible(view.get(), true);
            GuiEngine::GetInstance().SetTrText(view.get(), "delete");
        }
        /**
         * @brief
         * 显示输入法切换按键
         */
        if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "button2", true, view.get())) {
            GuiEngine::GetInstance().SetVisible(view.get(), true);
        }
        /**
         * @brief
         * 隐藏设置项值，用编辑框替换
         */
        if (GuiEngine::GetInstance().Lookup(editView, "valueString", true, view.get())) {
            GuiEngine::GetInstance().SetVisible(view.get(), false);
        }
        // else
        // {
        //     LOG_E("can't find the value string. edit's name = %s\n", editView->Name().c_str());
        // }
        SaveItem();
        SetEdit(editView, CURSOR_WIDTH, nullptr, mEditLength, editValue);
        RefreshPageEvent();
        EditShowValue();
    }
    // else
    // {
    //     LOG_E("can't init the input method.\n");
    // }
}
void InputItem::InputUnInitIQ()
{
    if (!inputMethodInit) {
        return;
    }
    if (!editView->IsValid()) {
        return;
    }
    /**
     * @brief
     * 恢复显示设置项的值
     */
    std::unique_ptr<Widget> view(GuiEngine::GetInstance().NewWidget());
    if (GuiEngine::GetInstance().Lookup(editView, "valueString", true, view.get())) {
        GuiEngine::GetInstance().SetVisible(view.get(), true);
        if (GuiEngine::GetInstance().Lookup(editView, EDIT_VALUE, true, view.get())) {
            GuiEngine::GetInstance().Destroy(view.get());
        } else {
            LOG_E("can't find edit value view.\n");
        }
    }
    // else
    // {
    //     LOG_E("can't find value string view.\n");
    // }
    /**
     * @brief
     * 销毁候选字符view
     */
    if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "choose", true, view.get())) {
        GuiEngine::GetInstance().Destroy(view.get());
    }
    /**
     * @brief
     * 销毁输入法切换view
     */
    if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "imchoose", true, view.get())) {
        GuiEngine::GetInstance().Destroy(view.get());
    }
    /**
     * @brief
     * 隐藏和设置删除键
     */
    if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "button3", true, view.get())) {
        // GuiEngine::GetInstance().SetVisible(view.get(), false);
        GuiEngine::GetInstance().SetTextUtf8(view.get(), "");
    }
    /**
     * @brief
     * 隐藏输入法切换按键
     */
    if (GuiEngine::GetInstance().Lookup(InputItem::primaryWidget.get(), "button2", true, view.get())) {
        // GuiEngine::GetInstance().SetVisible(view.get(), false);
        GuiEngine::GetInstance().SetTextUtf8(view.get(), "");
    }
    SaveItemExit();
    inputMethodInit = false;
}
void InputItem::Input(void* ctx)
{
    if (!EditValueCheck(editValue, GetChoosing())) {
        LOG_W("edit value check false, check your input.\n");
        return;
    }
    InputOperation(ctx);
    RefreshPageEvent();
}
void InputItem::Delete(void* ctx)
{
    InputMethod::Delete(ctx);
    // RefreshPageEvent();
}
void InputItem::InputMethodChange(void* ctx)
{
    InputMethod::InputMethodChange();
    // RefreshPageEvent();
}
void InputItem::ResetKeyCmd(KeyCmdMapTable& keyEvent)
{
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_2)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_3)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_SOFT_KEY_4)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_OK)] = KeyCmd::CTX_CMD_MENU_WIN_ENTER;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_0)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_1)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_2)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_3)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_4)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_5)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_6)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_7)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_8)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_NUM_9)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_ASTERISK)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_POUND_SIGN)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_DIRECTION_LEFT)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    keyEvent.table[static_cast<int>(KeyboardValue::KEY_DIRECTION_RIGHT)] = KeyCmd::KEY_CMD_CONTRL_SECOND_PAGE;
    // PageHandle* window = (PageHandle*)Interface::GetInstance().GetCurrentWin();
    // window->SetKeyEvent(keyEvent);
    SecondPage::ResetKeyCmd(keyEvent);
}
void InputItem::SetEditText(Widget* edit, std::string value, void* ctx)
{
    /**
     * @brief
     * 开始显示字符下标。
     */
    editValue = value;
    RefreshPageCommon(GetString());
    std::unique_ptr<Widget> view(GuiEngine::GetInstance().NewWidget());
    if (GuiEngine::GetInstance().Lookup(edit, EDIT_VALUE, true, view.get())) {
        GuiEngine::GetInstance().Destroy(view.get());
    }
    if (GuiEngine::GetInstance().ViewCreate(edit, 0, 0, 0, 0, view.get())) {
        GuiEngine::GetInstance().SetName(view.get(), EDIT_VALUE);
        GuiEngine::GetInstance().UseStyle(view.get(), "inputView");
        GuiEngine::GetInstance().SetFloating(view.get(), true);
        if (commonItem) {
            /**
             * @brief
             * 默认为通用设置项，输入框靠右放置。
             */
            GuiEngine::GetInstance().SetSelfLayout(view.get(), "default(x=r:12,y=m,w=52%,h=96%)");
        } else {
            /**
             * @brief
             * 派生设置项靠左放置
             */
            GuiEngine::GetInstance().SetSelfLayout(view.get(), "default(x=5,y=m,w=98%,h=96%)");
        }
        /**
         * @brief
         * 设置项view控件有1行、1列，设置项按数量靠左排列
         */
        GuiEngine::GetInstance().SetChildrenLayout(view.get(), "default(r=1,c=0,align_h=left,x=0,y=0,s=0)");
        std::unique_ptr<Widget> view2(GuiEngine::GetInstance().NewWidget());
        for (unsigned int i = GetStartIndex(); i < value.length(); i++) {
            if (GuiEngine::GetInstance().LabelCreate(view.get(), 0, 0, 0, 0, view2.get())) {
                SetEditString(view2.get(), value, i);
            }
            if (i - GetStartIndex() + 1 >= mEditLength) {
                break;
            }
        }
    }
}
void InputItem::InputMethodSelection(InputMethodsType& method, InputMethodsType& lastMethod)
{
    if (InputMethodsType::FUNCTION_END == onlySupport) {
        InputMethod::InputMethodSelection(method, lastMethod);
        return;
    }
    lastMethod = InputMethodsType::FUNCTION_END;
    method = onlySupport;
}
std::string InputItem::GetString()
{
    return editValue;
}
void InputItem::RefreshPage()
{
    RefreshPageCommon(GetString());
}
void InputItem::SetOnlySupport(InputMethodsType type)
{
    onlySupport = type;
    SetInputMethodType(type);
}
void InputItem::SaveData(void* ctx)
{
    SecondPage* window = dynamic_cast<SecondPage*>(Interface::GetInstance().GetCurrentWin());
    if (window) {
        window->SaveConfiguration();
    } else {
        LOG_E("current window can't save anything.\n");
    }
}
std::string InputItem::GetValueByIndex(std::string value, unsigned int index)
{
    return value.substr(index, 1);
}
void InputItem::SetEditString(Widget* widget, std::string value, unsigned int index)
{
    char text[256] = { 0 };
    snprintf(text, 256, "default(w=%d,h=100%%)", CURSOR_WIDTH);
    GuiEngine::GetInstance().SetSelfLayout(widget, text);
    GuiEngine::GetInstance().SetTextUtf8(widget, GetValueByIndex(value, index).c_str());
    GuiEngine::GetInstance().UseStyle(widget, "inputEdit");
}
std::string& InputItem::GetEditValue()
{
    return editValue;
}
void InputItem::ShowEditTips(Widget* inputView)
{
    std::unique_ptr<Widget> view2(GuiEngine::GetInstance().NewWidget());
    if (GuiEngine::GetInstance().LabelCreate(inputView, 0, 0, 0, 0, view2.get())) {
        GuiEngine::GetInstance().SetSelfLayout(view2.get(), "default(w=100%,h=100%)");
        GuiEngine::GetInstance().SetTrText(view2.get(), editTips.c_str());
        GuiEngine::GetInstance().UseStyle(view2.get(), "inputTips");
    }
}
void InputItem::SetEditTips(std::string tips)
{
    editTips = tips;
}
unsigned int InputItem::GetEditLength()
{
    return mEditLength;
}